using System;
using OhioState.Math;

namespace OhioState.Graphics
{
    /// <summary>
    /// This class implements a viewport with standard viewport 
    /// parameters such as origin, aspect ratio, etc.
    /// </summary>
    [Serializable()]
    public class Viewport
    {
        #region Public properties

        /// <summary>
        /// Get or set whether dimensions are fixed or not.
        /// </summary>
        public bool FixedDimension
        {
            get { return _fixedDimension; }
            set { _fixedDimension = value; }
        }

        /// <summary>
        /// Get or set aspect ratio.
        /// </summary>
        public bool AspectFixed
        {
            get { return _aspectFixed; }
            set
            {
                _aspectFixed = value;
                this.Width = _width;
            }
        }
        
        /// <summary>
        /// Get or set viewport origin.
        /// </summary>
        public Vector2i Origin
        {
            get { return _origin; }
            set { _origin = value; }
        }

        /// <summary>
        /// Get or set viewport width.
        /// </summary>
        public int Width
        {
            get { return _width; }
            set
            {
                if (!_fixedDimension)
                {
                    _width = value;
                    if (_aspectFixed)
                    {
                        _height = (int)(((float)_width) / _aspectRatio);
                    }
                }
            }
        }

        /// <summary>
        /// Get or set viewport height.
        /// </summary>
        public int Height
        {
            get { return _height; }
            set
            {
                if (!_fixedDimension)
                {
                    _height = value;
                    if (_aspectFixed)
                    {
                        _width = (int)(((float)_height) * _aspectRatio);
                    }
                }
            }
        }

        /// <summary>
        /// Get or set aspect ratio.
        /// </summary>
        public float AspectRatio
        {
            get { return _aspectRatio; }
            set
            {
                _aspectRatio = value;
                if (_aspectRatio < MIN_ASPECT) _aspectRatio = MIN_ASPECT;
                if (_aspectRatio > MAX_ASPECT) _aspectRatio = MAX_ASPECT;
                this.Width = _width;
            }
        }

        #endregion

        #region Constructors
        /// <summary>
        /// Create a new viewport with default parameters:
        /// Origin at (0, 0) and size 100x100.
        /// </summary>
        public Viewport()
            : this(new Vector2i(0, 0), new Vector2i(100, 100))
        {
        }

        /// <summary>
        /// Create a new viewport.
        /// </summary>
        /// <param name="origin">Coordinates of the origin.</param>
        /// <param name="dimensions">Dimensions of the viewport.</param>
        public Viewport(Vector2i origin, Vector2i dimensions)
        {
            _aspectFixed = false;
            _fixedDimension = false;
            _aspectRatio = 1.0f;
            _origin = new Vector2i(origin);
            _width = dimensions.x;
            _height = dimensions.y;
        }
        #endregion

        #region Static parameters

        private static readonly float MAX_ASPECT = 2048.0f;
        private static readonly float MIN_ASPECT = 1.0f / MAX_ASPECT;

        #endregion

        #region Private memebers

        private float _aspectRatio;
        private int _height;
        private int _width;
        private Vector2i _origin;
        private bool _aspectFixed;
        private bool _fixedDimension;
        
        #endregion

        #region ToString
        /// <summary>
        /// Returns all viewport parameters in a string.
        /// </summary>
        /// <returns>String representation of all viewport parameters.</returns>
        public override string ToString()
        {
            return "Viewport::"
                + "   FixedDimension = " + _fixedDimension.ToString()
                + "   Aspect Ratio Fixed = " + _aspectFixed.ToString()
                + "   Origin = " + _origin.ToString()
                + "   Width = " + _width.ToString()
                + "   Height = " + _height.ToString()
                + "   Aspect Ratio = " + _aspectRatio.ToString();
        }
        #endregion
    }
}
